package com.fsm.common.xxljob;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import java.net.HttpCookie;
import java.util.*;

/**
 * SpringBoot-XXLJOB提供OpenAPI调度任务
 */
@Component
public class XxlJobUtil {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public static final String CODE = "code";
    public static final String XXL_JOB_ACCESS_TOKEN = "XXL_JOB_LOGIN_IDENTITY";
    private static final String ADD_URL = "http://127.0.0.1:8087/xxl-job-admin/jobinfo/add";
    private static final String INFO_URL = "http://127.0.0.1:8087/xxl-job-admin/jobinfo/pageList";
    private static final String UPDATE_URL = "http://127.0.0.1:8087/xxl-job-admin/jobinfo/update";
    private static final String REMOVE_URL = "http://127.0.0.1:8087/xxl-job-admin/jobinfo/remove";
    private static final String PAUSE_URL = "/api/pauseJob";
    private static final String START_URL = "http://127.0.0.1:8087/xxl-job-admin/jobinfo/start";
    private static final String STOP_URL = "http://127.0.0.1:8087/xxl-job-admin/jobinfo/stop";
    private static final String ADD_START_URL = "/api/addAndStart";
    private static final String GET_GROUP_ID = "/api/getGroupId";

    /**
     * 新增job
     * {\"jobGroup\":\"1\",\"jobDesc\":\"test_des\",\"author\":\"admin\",\"alarmEmail\":\"\",\"scheduleType\":\"CRON\",\"scheduleConf\":\"0 0 0 * * ? *\",
     * \"cronGen_display\":\"0 0 0 * * ? *\",\"schedule_conf_CRON\":\"0 0 0 * * ? *\",\"schedule_conf_FIX_RATE\":\"\",\"schedule_conf_FIX_DELAY\":\"\",
     * \"glueType\":\"BEAN\",\"executorHandler\":\"demoJobHandler\",\"executorParam\":\"\",\"executorRouteStrategy\":\"FIRST\",\"childJobId\":\"\",
     * \"misfireStrategy\":\"DO_NOTHING\",\"executorBlockStrategy\":\"SERIAL_EXECUTION\",\"executorTimeout\":\"0\",\"executorFailRetryCount\":\"1\",
     * \"glueRemark\":\"GLUE%E4%BB%A3%E7%A0%81%E5%88%9D%E5%A7%8B%E5%8C%96\",\"glueSource\":\"\"}
     */
    public Integer addJob(XxlJobInfo xxlJobInfo) throws Exception {
        Map<String,Object> map = new HashMap<>();
        //执行器ID
        map.put("jobGroup", 2);
        //任务描述
        map.put("jobDesc", xxlJobInfo.getJobDesc());
        //负责人
        map.put("author", "admin");
        //报警邮件
        map.put("alarmEmail", "");
        //调度类型
        map.put("scheduleType", "CRON");
        //Cron
        map.put("scheduleConf", xxlJobInfo.getScheduleConf());
        map.put("cronGen_display", xxlJobInfo.getScheduleConf());
        map.put("schedule_conf_CRON", xxlJobInfo.getScheduleConf());
        map.put("schedule_conf_FIX_RATE", "");
        map.put("schedule_conf_FIX_DELAY", "");
        //运行模式
        map.put("glueType", "BEAN");
        //JobHandler
        map.put("executorHandler", "myXxlJobHandler");
//        //任务参数
//        requestInfo.put("executorParam", String.format("%s,%s,%s", jobVo.getEquid(), jobVo.getDeviceId(), jobVo.getChannelId()));
        // 一致性hash
        map.put("executorRouteStrategy", "FIRST");
        map.put("childJobId", "");
        map.put("misfireStrategy", "DO_NOTHING");
        map.put("executorBlockStrategy", "SERIAL_EXECUTION");
        map.put("executorTimeout", "0");
        map.put("executorFailRetryCount", "0");
        map.put("glueRemark", "GLUE代码初始化");
        map.put("glueSource", "");
        String body = getRequestBody(map, ADD_URL, xxlJobInfo.getXxlJobToken());
        Integer id = 0;
        if (StrUtil.isNotBlank(body)) {
            JSONObject jsonObject = JSON.parseObject(body);
            if (jsonObject.getInteger(CODE) != 200) {
                logger.info("addJob error:{}", JSON.parseObject(body));
                throw new Exception("新增job失败");
            }
            logger.info("addJob success");
            id = jsonObject.getInteger("content");
        }
        return id;
    }

    /**
     * job查询
     */
    public Map<String,Object> infoJob(XxlJobInfo xxlJobInfo) {
        List<XxlJobInfo> oXxlJobInfoList = new ArrayList<>();
        Integer total = 0;
        Map<String,Object> map = new HashMap<>();
        map.put("jobGroup",2);
        map.put("triggerStatus",xxlJobInfo.getTriggerStatus());
        map.put("jobDesc","");
        map.put("executorHandler","");
        map.put("author","");
        map.put("start",xxlJobInfo.getStart());
        map.put("length",xxlJobInfo.getLength());
        String body = getRequestBody(map, INFO_URL, xxlJobInfo.getXxlJobToken());
        if (StrUtil.isNotBlank(body)) {
            JSONObject jsonObject = JSON.parseObject(body);
            if (jsonObject == null) {
                logger.info("infoJob error:{}", JSON.parseObject(body));
                return null;
            }
            Map<String, String> allJsonMap = JSONObject.parseObject(body, new TypeReference<HashMap<String, String>>() {
            });
            //转数组
            JSONArray jsonArray = JSONArray.parseArray(allJsonMap.get("data"));
            oXxlJobInfoList = jsonArray.toJavaList(XxlJobInfo.class);
            total = jsonObject.getInteger("recordsTotal");
            logger.info("infoJob success");
        }
        Map<String,Object> mapData = new HashMap<>();
        mapData.put("oXxlJobInfoList",oXxlJobInfoList);
        mapData.put("total",total);
        return mapData;
    }

    /**
     * 更新job
     */
    public Integer updateJob(XxlJobInfo xxlJobInfo) throws Exception {
        Map<String, Object> map = BeanUtil.beanToMap(xxlJobInfo);
        String body = getRequestBody(map, UPDATE_URL, xxlJobInfo.getXxlJobToken());
        if (StrUtil.isNotBlank(body)) {
            JSONObject jsonObject = JSON.parseObject(body);
            if (jsonObject.getInteger(CODE) != 200) {
                logger.info("updateJob error:{}", JSON.parseObject(body));
                throw new Exception("更新job失败");
            }
        }
        logger.info("updateJob success");
        return xxlJobInfo.getId();
    }

    /**
     * 启动job
     */
    public Integer startJob(XxlJobInfo xxlJobInfo) throws Exception {
        Map<String, Object> map = new HashMap<>();
        map.put("id",xxlJobInfo.getId());
        String body = getRequestBody(map, START_URL, xxlJobInfo.getXxlJobToken());
        if (StrUtil.isNotBlank(body)) {
            JSONObject jsonObject = JSON.parseObject(body);
            if (jsonObject.getInteger(CODE) != 200) {
                logger.info("startJob error:{}", JSON.parseObject(body));
                throw new Exception("启动job失败");
            }
        }
        logger.info("startJob success");
        return xxlJobInfo.getId();
    }

    /**
     * 停止job
     */
    public Integer stopJob(XxlJobInfo xxlJobInfo) throws Exception {
        Map<String, Object> map = new HashMap<>();
        map.put("id",xxlJobInfo.getId());
        String body = getRequestBody(map, STOP_URL, xxlJobInfo.getXxlJobToken());
        if (StrUtil.isNotBlank(body)) {
            JSONObject jsonObject = JSON.parseObject(body);
            if (jsonObject.getInteger(CODE) != 200) {
                logger.info("stopJob error:{}", JSON.parseObject(body));
                throw new Exception("停止job失败");
            }
        }
        logger.info("stopJob success");
        return xxlJobInfo.getId();
    }

    /**
     * 删除job
     */
    public Integer removeJob(XxlJobInfo xxlJobInfo) throws Exception {
        // 先停止job,再删除job
        try {
            stopJob(xxlJobInfo);
        }catch (Exception e){
            throw new Exception("删除job失败");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("id",xxlJobInfo.getId());
        String body = getRequestBody(map, REMOVE_URL, xxlJobInfo.getXxlJobToken());
        if (StrUtil.isNotBlank(body)) {
            JSONObject jsonObject = JSON.parseObject(body);
            if (jsonObject.getInteger(CODE) != 200) {
                logger.info("removeJob error:{}", JSON.parseObject(body));
                throw new Exception("删除job失败");
            }
        }
        logger.info("removeJob success");
        return xxlJobInfo.getId();
    }


    /**
     * 接口请求
     * uri：请求链接
     * token：权限token
     */
    private String getRequestBody(Map<String,Object> dateMap, String uri, String token) {
        HttpResponse httpResponse = HttpRequest.post(uri)
                .form(dateMap).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
                .cookie("XXL_JOB_LOGIN_IDENTITY=" + token).execute();
        return httpResponse.body();
    }

    /**
     * 登录返回token
     */
    public String loginJob() {
        String url="http://127.0.0.1:8087/xxl-job-admin/login";
        HttpResponse response = HttpRequest.post(url)
                .form("userName","admin")
                .form("password","123456")
                .execute();
        List<HttpCookie> cookies = response.getCookies();
        Optional<HttpCookie> cookieOpt = cookies.stream()
                .filter(cookie -> cookie.getName().equals("XXL_JOB_LOGIN_IDENTITY")).findFirst();
        if (!cookieOpt.isPresent())
            throw new RuntimeException("get xxl-job cookie error!");

        String value = cookieOpt.get().getValue();
        System.out.println(value);
        return value;
    }

}
